#include "common.h"
#include "msn_session.h"

static guint msn_user_hash(gconstpointer key);
static gboolean msn_user_equal(gconstpointer a, gconstpointer b);
static void msn_ns_connect_done(int fd, int error, int res, void *data);

static guint msn_user_hash(gconstpointer key)
{
	msn_user_t *user = (msn_user_t *)key;
	
	return g_string_hash(user->passport);
}

static gboolean msn_user_equal(gconstpointer a, gconstpointer b)
{
	msn_user_t *ua, *ub;

	ua = (msn_user_t *)a;
	ub = (msn_user_t *)b;
	return g_str_equal(ua->passport->str, ub->passport->str);
}

msn_ns_t *msn_ns_new(int fd, int port, struct in_addr addr)
{
	msn_ns_t *ns;

	g_return_val_if_fail(fd > 0, NULL);
	ns = g_new0(msn_ns_t, 1);
	ns->fd = fd;
	ns->port = port;
	ns->addr = addr;
	ns->in = g_string_new(NULL);
	ns->ev = xevent_new();
	xevent_set(ns->ev, ns->fd, SOCK_FLAG_WRITE, NULL, NULL);
	xevent_base_set(ns->ev, master_base);
	ns->timer = xevent_new();
	xevtimer_set(ns->timer, NULL, NULL);
	xevent_base_set(ns->timer, master_base);

	return ns;
}

void msn_ns_clean(msn_ns_t *ns)
{
	g_return_if_fail(ns!=NULL);
	xevent_clean(ns->ev);
	xevent_clean(ns->timer);
	g_string_free(ns->in, 1);
	g_free(ns);
}

/* msn session functions */
msn_session_t *msn_session_new(const char *name, const char *pass)
{
	g_return_val_if_fail(name!=NULL && pass!=NULL, NULL);
	msn_session_t *s = g_new0(msn_session_t, 1);
	
	s->name = g_string_new(name);
	s->pass = g_string_new(pass);
	/* init owner */
	s->owner = msn_user_new(name);
	s->owner->display_name = NULL;
	s->owner->store_name = NULL;
	/* init friends, need to read from share/contact_list.xml */
	s->friends = g_hash_table_new((GHashFunc)g_string_hash, (GEqualFunc)g_string_equal);
	/* switchs */
	s->switchs = NULL;
	/* init security tokens */
	s->sec_tokens = NULL;
	/* init ssl */
	s->ssl = SSL_new(sslcontext);
	/* init notify server */
	struct in_addr addr;
	int fd; 
	fd  = sock_open_from_host(MSN_NOTIFY_SERVER, &addr);
	if(fd == -1) {
		debug_log(0, "faied to open new socket for %s\n", MSN_NOTIFY_SERVER);
		return NULL;
	}
	s->ns = msn_ns_new(fd, 1863, addr);
	return s;
}	

void msn_session_clean(msn_session_t *ms)
{
	g_return_if_fail(ms != NULL);
	g_string_free(ms->name, 1);
	g_string_free(ms->pass, 1);
	msn_user_clean(ms->owner);
	g_string_free(ms->nonce, 1);
	g_hash_table_destroy(ms->friends);
	g_list_free(ms->switchs);
	g_list_free(ms->sec_tokens);
	msn_ns_clean(ms->ns);
}

